package com.zhuyi.broadcast.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuyi.broadcast.mapper.*;
import com.zhuyi.broadcast.pojo.domain.*;
import com.zhuyi.broadcast.service.ElementService;
import com.zhuyi.common.constant.BroadcastConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;


/**
 * <p>
 *  元素实现类
 * </p>
 *
 * @author dyj
 * @since 2024-12-12
 */

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class ElementServiceImpl extends ServiceImpl<ElementMapper, Element> implements ElementService {

    @Autowired
    private ResourceMapper resourceMapper;

    @Autowired
    private ElementResourceRelationMapper elementResourceRelationMapper;

    @Autowired
    private ProgramElementRelationMapper programElementRelationMapper;

    @Autowired
    private ProgramMapper programMapper;

    @Autowired
    private ElementMapper elementMapper;

    /**
     * 查询所有可用的元素列表
     */
    public List<Element> selectAvailableElements(Element element) {
        return this.baseMapper.selectList(
                new LambdaQueryWrapper<Element>()
                        .eq(Element::getHideFlag, 0)
        );
    }

    /**
     * 查询节目中的元素列表
     */
    public List<ProgramElementRelation> getElementsListByProgramId(Long programId) {
        // 检查节目ID是否存在
        Long count = programMapper.selectCount(
                new QueryWrapper<Program>()
                        .inSql("id", "SELECT id FROM bc_program WHERE id = " + programId)
        );

        // 如果节目ID不存在，抛出异常或返回空结果
        if (count == 0) {
            throw new IllegalArgumentException("没有该节目: " + programId);
            // 或者直接返回空列表
            // return Collections.emptyList();
        }

        return programElementRelationMapper.selectList(
                new QueryWrapper<ProgramElementRelation>()
                        .inSql("element_id", "SELECT element_id FROM bc_relation_element_program WHERE program_id = " + programId)
        );
    }

    /**
     * 获取指定节目中的指定元素的详细信息
     * @param programId 节目 ID
     * @param elementId 元素 ID
     * @return Element 返回元素的详细信息
     */
    public ProgramElementRelation getElementByProgramId(Long programId, Long elementId) {
        return programElementRelationMapper.selectOne(new LambdaQueryWrapper<ProgramElementRelation>()
                .eq(ProgramElementRelation::getProgramId, programId)
                .eq(ProgramElementRelation::getElementId, elementId)
        );
    }

    /**
     * 将元素添加至指定节目
     * @param elementId 元素ID
     * @param programId 节目ID
     * @return 是否成功
     */
    public boolean addElementToProgram(Long programId, Long elementId) {
        ProgramElementRelation relation = new ProgramElementRelation();
        relation.setProgramId(programId);
        relation.setElementId(elementId);
        relation.setWidth(BroadcastConstants.ELEMENT_DEFAULT_WIDTH);
        relation.setHeight(BroadcastConstants.ELEMENT_DEFAULT_HEIGHT);

        return programElementRelationMapper.insert(relation) > 0;
    }

    /**
     * 保存元素
     * @param elementId 元素名称
     * @return 是否成功
     */
    public boolean saveElement(Long elementId) {
        Element element = this.baseMapper.selectById(elementId);
        element.setHideFlag(0);
        return this.baseMapper.updateById(element) > 0;
    }

    /**
     * 添加元素到列表
     * @param elementName 元素名称
     * @return 是否成功
     */
//    public boolean addElement(String elementName) {
//        Element element = new Element();
//        element.setElementName(elementName);
//        element.setHideFlag(1);

//        return this.baseMapper.insert(element) > 0;
//    }

    /**
     * 从指定节目中删除元素
     * @param programId 节目ID
     * @param elementId 元素ID
     * @return 是否成功
     */
    public boolean removeElementFromProgram(Long programId, Long elementId) {
        return programElementRelationMapper.delete(
                new LambdaUpdateWrapper<ProgramElementRelation>()
                        .eq(ProgramElementRelation::getProgramId, programId)
                        .eq(ProgramElementRelation::getElementId, elementId)
        ) > 0;
    }

    /**
     * 删除元素
     * @param elementId 元素ID
     * @return 是否成功
     * 待优化
     */
    public boolean removeElement(Long elementId) {
        // 检查元素是否与节目有关联
        if(programElementRelationMapper.selectCount(
                new LambdaQueryWrapper<ProgramElementRelation>()
                        .eq(ProgramElementRelation::getElementId,elementId))>0){
            System.out.println("该元素正在被节目使用，无法删除");
            return false;
        }

        // 删除元素及其附庸
        delete_ele(elementId);
        return true;
    }

    /**
     * 更新指定节目中的某个元素
     * @param programId 节目 ID
     * @param elementId 元素 ID
     * @param params 包含更新内容的请求对象
     * @return boolean 是否更新成功
     */
    public boolean updateElement(Long programId, Long elementId, Map<String, String> params) {
        // 检查元素是否存在于指定节目中
        int count = Math.toIntExact(programElementRelationMapper.selectCount(
                new LambdaQueryWrapper<ProgramElementRelation>()
                        .eq(ProgramElementRelation::getProgramId, programId)
                        .eq(ProgramElementRelation::getElementId, elementId)
        ));

        if (count == 0) {
            return false; // 元素不在该节目中，更新失败
        }

        // 使用 LambdaUpdateWrapper 更新元素
        LambdaUpdateWrapper<ProgramElementRelation> updateWrapper = Wrappers.lambdaUpdate(ProgramElementRelation.class)
                .eq(ProgramElementRelation::getElementId, elementId)
                .set(params.containsKey("xPosition"), ProgramElementRelation::getXPosition, Integer.parseInt(params.get("xPosition")))
                .set(params.containsKey("yPosition"), ProgramElementRelation::getYPosition, Integer.parseInt(params.get("yPosition")))
                .set(params.containsKey("width"), ProgramElementRelation::getWidth, Integer.parseInt(params.get("width")))
                .set(params.containsKey("height"), ProgramElementRelation::getHeight, Integer.parseInt(params.get("height")));

        // 更新元素
        return programElementRelationMapper.update(null,updateWrapper)>0;
    }





    /**
     * 将资源添加到元素
     * @param elementId 元素ID
     * @param resourceId 资源ID
     * @return 操作是否成功
     */
    public boolean addResourceToElement(Long elementId, Long resourceId) {
        // 查询资源
        Resource resource = resourceMapper.selectById(resourceId);
        if (resource == null) {
            throw new RuntimeException("资源不存在");
        }

        // 查询元素
        if (this.baseMapper.selectById(elementId) == null) {
            throw new RuntimeException("元素不存在");
        }

        // 查询元素与资源的关联关系
        ElementResourceRelation existingRelation = elementResourceRelationMapper.selectOne(
                new LambdaQueryWrapper<ElementResourceRelation>()
                        .eq(ElementResourceRelation::getElementId, elementId)
        );

        if (existingRelation != null) {
            // 如果已有关联关系，检查资源类型是否匹配
            Resource associatedResource = resourceMapper.selectById(existingRelation.getResourceId());
            if (associatedResource == null) {
                throw new RuntimeException("关联的资源不存在");
            }

            // 判断元素的资源类型和当前资源的类型是否一致
            if (!associatedResource.getResourceType().equals(resource.getResourceType())) {
                throw new RuntimeException("元素类型和资源类型不匹配");
            }
        } else {
            // 如果没有关联关系，直接插入新的关联关系
            ElementResourceRelation relation = new ElementResourceRelation();
            relation.setElementId(elementId);
            relation.setResourceId(resourceId);
            elementResourceRelationMapper.insert(relation);
        }

        return true;
    }




    /**
     * 查询元素中的资源列表
     */
    public List<ElementResourceRelation> getResourcesListByElementId(Long elementId) {
        // 检查元素ID是否存在
        Long count = this.baseMapper.selectCount(
                new QueryWrapper<Element>()
                        .inSql("id", "SELECT element_id FROM bc_relation_element_program WHERE element_id = " + elementId)
        );

        // 如果元素ID不存在，抛出异常或返回空结果
        if (count == 0) {
            throw new IllegalArgumentException("没有该元素: " + elementId);
            // 或者直接返回空列表
            // return Collections.emptyList();
        }

        return elementResourceRelationMapper.selectList(
                new QueryWrapper<ElementResourceRelation>()
                        .inSql("resource_id", "SELECT resource_id FROM bc_relation_resource_element WHERE element_id = " + elementId)
        );
    }

    /**
     * 从元素中移除资源（仅表示不再使用资源）
     * @param elementId 元素ID
     * @param resourceId 资源ID
     * @return 是否移除成功
     */
    public boolean removeResourceFromElement(Long elementId, Long resourceId) {
        return elementResourceRelationMapper.delete(
                new LambdaQueryWrapper<ElementResourceRelation>()
                        .eq(ElementResourceRelation::getElementId, elementId)
                        .eq(ElementResourceRelation::getResourceId, resourceId)
        ) > 0;
    }

    /**
     * 更新资源
     * @param elementId 元素 ID
     * @param resourceId 资源 ID
     * @param config 配置 JSON
     * @return 是否更新成功
     */
    @Override
    public boolean updateResource(Long elementId, Long resourceId, String config) {
        LambdaUpdateWrapper<ElementResourceRelation> updateWrapper = Wrappers.lambdaUpdate(ElementResourceRelation.class)
                        .eq(ElementResourceRelation::getElementId, elementId)  // 匹配元素 ID
                        .eq(ElementResourceRelation::getResourceId, resourceId)  // 匹配资源 ID
                        .set(ElementResourceRelation::getConfig, config);  // 更新 config 字段
        return elementResourceRelationMapper.update(null,updateWrapper)>0;
    }


    /**
     * 删除元素及其附庸
     * @param elementId
     * @return
     */
    public void delete_ele(Long elementId){

        // 删除元素和资源的关联
        elementResourceRelationMapper.delete(
                new LambdaQueryWrapper<ElementResourceRelation>()
                        .eq(ElementResourceRelation::getElementId,elementId)
        );

        // 删除元素
        elementMapper.delete(
                new LambdaUpdateWrapper<Element>()
                        .eq(Element::getId, elementId)
        );

    }
}
